<div class="setup container">
	<div class="span6 fullwidth">
	   	<img src="img/logo.gif"/>
		<ul class="nav nav-pills">
			<li role="presentation" class="active"><a class="welcomeBtn">Welcome</a></li>
			<li role="presentation"><a class="adminBtn">Admin Account</a></li>
			<li role="presentation"><a class="emailBtn">Email</a></li>
			<li role="presentation"><a class="pluginsBtn">Plugins</a></li>
			<li role="presentation"><a class="extendedDataSchemasBtn">Extended Data Schemas</a></li>
			<li role="presentation"><a class="finishBtn">Finish</a></li>
		</ul>
		
		<div class="setupContent">
			<div class="contentdiv welcome">
				<div class="well well-sm">
					<p>
					Welcome,<br/>
					This wizard will help you setup your BIMserver.</p>
					<b>Address</b>
					<p>The address your BIMserver will be available from. It will be pre-filled, but this is not necessarily the right address. If you are using a domain name, make sure to use it here.</p>
					<b>Name/Description/Icon</b>
					<p>Information that identifies this specific BIMserver instance. Remote servers will show this information for a user to identify this BIMserver.</p>
				</div>
				<form class="form-horizontal">
					<div class="form-group">
						<label for="inputSiteAddress">Site address</label>
						<input type="text" class="siteAddressInput form-control" id="inputSiteAddress"/>
					</div>
					<div class="form-group">
						<label for="inputServerName">Server name</label>
						<input type="text" class="serverNameInput form-control" id="inputServerName" placeholder="My BIMserver"/>
					</div>
					<div class="form-group">
						<label for=inputIdentifier>Server identifier</label>
						<input type="text" class="identifierInput form-control" id="inputIdentifier"/>
					</div>
					<div class="form-group">
						<label for="inputServerDescription">Server description</label>
						<input type="text" class="serverDescriptionInput form-control" id="inputServerDescription"/>
					</div>
					<div class="form-group">
						<label for="inputServerIcon">Server icon</label>
						<input type="text" class="severIconInput form-control" id="inputServerIcon" value="/img/bimserver.png"/>
						<div>
							<img class="serverIcon" src="/img/bimserver.png"/>
						</div>
					</div>
				</form>
				<button class="btn btn-default adminBtn">Next</button>
			</div>
	
			<div class="contentdiv admin">
				<div class="well well-sm">
					You have to setup one administrator account (you can add more later). If you want to be able to reset your password, make sure to provide a working email address (and setup a mail server in the next step).
				</div>
				<form class="form-horizontal">
					<div class="form-group">
						<label for="inputAdminName">Administrator name</label> <input type="text" class="adminNameInput form-control" id="inputAdminName" value="Administrator">
					</div>
					<div class="form-group">
						<label for="inputAdminUsername">Administrator username</label>
						<div class="input-group">
							<span class="input-group-addon">@</span> <input type="text" class="adminUsernameInput form-control" id="inputAdminUsername" placeholder="Username (e-mail address)">
						</div>
					</div>
					<div class="form-group">
						<label for="inputAdminPassword">Administrator password</label>
						<div class="input-group">
							<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span> <input type="password" class="adminPasswordInput form-control" id="inputAdminPassword">
						</div>
					</div>
				</form>
				<button class="btn btn-default emailBtn">Next</button>
			</div>
	
			<div class="contentdiv email">
				<div class="well well-sm">
					Setting up email is optional. Emails can be send for:
					<ul>
						<li>New user registration</li>
						<li>Password reset</li>
						<li>New revision notifications</li>
						<li>Compare results</li>
					</ul>
					You can use an existing company email server, setup your own mailserver (only recommended for experienced sysadmins), or use an online email provider like mailgun.
				</div>
				<form class="form-horizontal">
					<div class="checkbox">
						<label> <input class="emailCheckBox" type="checkbox"> Use an email server
						</label>
					</div>
					<div class="emailDiv">
						<div class="form-group">
							<label class="control-label" for="smtpServer"><a rel="tooltip" data-original-title="SMTP server to use for sending emails" data-placement="right">SMTP
									server</a></label> <input type="text" class="form-control smtpServer" id="smtpServer" placeholder="Address">
						</div>
						<div class="form-group">
							<label class="control-label" for="smtpUsername"><a rel="tooltip" data-original-title="SMTP username" data-placement="right">SMTP username</a></label> <input
								type="text" class="form-control smtpUsername" id="smtpUsername" placeholder="SMTP username">
						</div>
						<div class="form-group">
							<label class="control-label" for="smtpPassword"><a rel="tooltip" data-original-title="SMTP password" data-placement="right">SMTP password</a></label> <input
								type="password" class="form-control smtpPassword" id="smtpPassword" placeholder="SMTP password">
						</div>
						<div class="form-group">
							<label class="control-label" for="smtpPort"><a rel="tooltip" data-original-title="SMTP port" data-placement="right">SMTP port</a></label> <input type="text"
								class="form-control smtpPort" id="smtpPort" placeholder="SMTP port" value="25">
						</div>
						<div class="form-group">
							<label class="control-label" for="smtpProtocol"><a rel="tooltip" data-original-title="SMTP protocol" data-placement="right">SMTP protocol</a></label> <select
								class="form-control smtpProtocol" id="smtpProtocol">
								<option value="SMTP">SMTP</option>
								<option value="SMTPS">SMTPS</option>
							</select>
						</div>
						<div class="form-group">
							<label class="control-label" for="emailSenderAddress"><a rel="tooltip" data-original-title="Email address to send emails from" data-placement="right">E-mail
									sender address</a></label> <input type="text" class="form-control emailSenderAddress" id="emailSenderAddress" placeholder="Name">
						</div>
						<div class="form-group">
							<label class="control-label" for="emailSenderName"><a rel="tooltip" data-original-title="Name to use for sending emails" data-placement="right">E-mail
									sender name</a></label> <input type="text" class="form-control emailSenderName" id="emailSenderName" placeholder="Name">
						</div>
					</div>
				</form>
				<button class="btn btn-default pluginsBtn">Next</button>
			</div>
	
			<div class="contentdiv plugins">
				<div class="well well-sm">
					<p>
						A BIMserver without plugins will be pretty useless, so we have selected a few plugins that you might want to install. You can install more plugins after the setup. Please note that for installing plugins this way, your BIMserver will have to have a working (outgoing) internet connection.
					</p>
					<p>
						For all selected plugins the latest version available for this version of BIMserver will be downloaded and installed. Currently the amount of work to check each plugin against each version of BIMserver is simply too much. For this reason the amount of available plugins can be limited for certain versions of BIMserver.
					</p>
					<p>
						<b>No internet connection</b>
						You can also <a class="btnUploadPlugins">upload JAR files of plugins</a> to install them, this is not the recommended way. Make sure you disable the checkboxes for the auto-installed plugin bundles.
					</p>
				</div>
				<div class="list-group">
				<div class="media list-group-item uploadPlugins ih">
					Upload plugin JAR files
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="bimviews" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; ; height: 153px; padding: 0px"><img class="media-object" height="150" src="img/bimviews.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">BIMvie.ws</h4>
						A web application that has the following features:
						<ul>
						<li>BIMserver administration (add users, install plugins, manage server settings, create projects etc...)</li>
						<li>Project-tree viewer</li>
						<li>3D viewer (BIMsurfer)</li>
						<li>Object browser</li>
						<li>Query tools</li>
						<li>Upload/download models</li>
						</ul>
						
						<br/>
						<span class="label label-warning">Not installing</span> Access to BIMserver functionality will be limited to the technical interfaces JSON, SOAP and Protocol Buffers and no GUI will be available if this plugin is not installed.
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="bimsurfer3" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; ; height: 153px; padding: 0px"><img class="media-object" height="150" src="img/opensourcebim.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">BIMsurfer 3</h4>
						A 3D viewer for BIM models. This is not a standalone application but a (JavaScript) library, it does however contain a few example applications, which is why we include it here anyways.
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="ifcopenshellplugin" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/ifcopenshell_logo.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">IfcOpenShell</h4>
						The open source ifc toolkit and geometry engine.<br/><br/>
						
						<span class="label label-warning">Not installing</span> Without this plugin BIMserver will not be able to convert IFC geometry to triangles, and thus no viewers will be able to visualize the model in 3D
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="ifcplugins" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/opensourcebim.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">IfcPlugins</h4>
						Contains serializers and deserializers for IFC and IfcXML and IfcJSON<br/><br/>
						<span class="label label-warning">Not installing</span> Without this plugin BIMserver will not be able to read/write IFC
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="binaryserializers" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/opensourcebim.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">BinarySerializers</h4>
						Contains binary serializers required for loading geometry in most of the viewers<br/><br/>
						<span class="label label-warning">Not installing</span> Without this plugin BIMsurfer/BIMvie.ws and possiblt other viewers will not be able to load 3D geometry
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="console" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/opensourcebim.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">Console</h4>
						Webbased user interface for calling methods of the BIMserver API and reading the documentation<br/>
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="gltf" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/gltf.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">glTF</h4>
						glTF 1 (with binary extension) and glTF 2 (glb) serializers<br/>
					</div>
				</div>
				<div class="media list-group-item maven">
					<div class="media-left media-middle">
						<input type="checkbox" class="mergers" checked="checked"/>
					</div>
					<div class="media-left">
						<div class="well" style="width: 260px; height: 153px; padding: 10px"><img class="media-object" height="130" style="margin-left: auto; margin-right: auto" src="img/opensourcebim.png"></div>
					</div>
					<div class="media-body">
						<h4 class="media-heading">Default mergers</h4>
						Default merger plugins, used for combining multiple IFC models into one IFC model<br/>
					</div>
				</div>
				</div>
				<button class="btn btn-default extendedDataSchemasBtn">Next</button>
				<br/><br/>
			</div>

			<div class="contentdiv extendeddataschemas">
				<div class="well well-sm">
					<div class="txt">To communicate with other BIM-enabled servers, a set of <a href="https://github.com/opensourceBIM/BIMserver-Repository/wiki/Extended-Data-Schemas">Extended Data Schemas</a> is available. You need a working internet connection _from_ your BIMserver for this to work.</div>
				</div>
				<div>
				<label>Install all extended data schemas <input type="checkbox" class="installExtendedDataSchemas" checked="checked"></label>
				</div>
				<button class="btn btn-default finishBtn">Next</button>
			</div>
			
			<div class="contentdiv finish">
				<div class="well well-sm">
					<div class="txt">Click the "Setup" button to finish the setup process</div>
				</div>
				<pre class="log ih"></pre>
				<button type="button" class="setupButton btn btn-primary">Setup</button><br/>
			</div>
		</div>
	</div>
</div>
<script>
function Setup(cd, address) {
	var o = this;
	o.level = 0;
	o.pluginsInstalled = {};
	
	if (address.endsWith(":80")) {
		address = address.substring(0, address.length - 3);
	}
	$(".setup .siteAddressInput").val(address);
	
	$(".emailCheckBox").change(function(){
		$(".emailDiv").toggle($(this).is(":checked"));
	});
	
	o.stage = 0;
	
	this.showWelcome = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".welcomeBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".welcome").show();
	};

	this.showAdmin = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".adminBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".admin").show();
	};

	this.showEmail = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".emailBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".email").show();
	};
	
	this.showPlugins = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".pluginsBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".plugins").show();
	};

	this.showExtendedDataSchemas = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".extendedDataSchemasBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".extendeddataschemas").show();
	};

	this.showFinish = function(){
		cd.find(".nav-pills .active").removeClass("active");
		cd.find(".finishBtn").parent().addClass("active");
		cd.find(".contentdiv").hide();
		cd.find(".finish").show();
	};
	
	this.fileChange = function(e){
		var plugin = $("<div>");
		plugin.addClass("media");
		plugin.addClass("list-group-item");
		plugin.addClass("uploaded");
		
		var middle = $("<div class=\"media-left media-middle\">");
		var checkbox = $("<input type=\"checkbox\" checked=\"checked\">");
		middle.append(checkbox);

		var mediaBody = $("<div class=\"media-body\">");

		plugin.append(middle);
		plugin.append(mediaBody);
		
		mediaBody.append("<h4 class=\"media-heading\">" + e.currentTarget.files[0].name + "</h4>");
	
		cd.find(".uploadPlugins").after(plugin);
		var file = $(e.currentTarget);
		file.hide();
		file.detach().appendTo(plugin);
		
		var file = $("<input type=\"file\" class=\"form-control fileInput\"/>");
		cd.find(".uploadPlugins").append(file);
		file.change(o.fileChange);
	};
	
	this.showUploadPlugins = function(){
		var uploadDiv = cd.find(".uploadPlugins");
		uploadDiv.show();
		if (uploadDiv.find(".fileInput").length == 0){
			var file = $("<input type=\"file\" class=\"form-control fileInput\"/>");
			file.change(o.fileChange);
			cd.find(".uploadPlugins").append(file);
		}
	};
	
	cd.find(".welcomeBtn").click(o.showWelcome);
	cd.find(".adminBtn").click(o.showAdmin);
	cd.find(".emailBtn").click(o.showEmail);
	cd.find(".pluginsBtn").click(o.showPlugins);
	cd.find(".extendedDataSchemasBtn").click(o.showExtendedDataSchemas);
	cd.find(".finishBtn").click(o.showFinish);
	cd.find(".welcome").show();
	cd.find(".btnUploadPlugins").click(o.showUploadPlugins);
	
	this.incLevel = function(){
		o.level++;
	};
	
	this.decLevel = function(){
		o.level--;
	};
	
	this.logError = function(message){
		for (var i=0; i<o.level; i++) {
			message = "\t" + message;
		}
		cd.find(".finish pre").append("<span class=\"error\">" + message + "</span>\n");
	};
	
	this.logInfo = function(message){
		for (var i=0; i<o.level; i++) {
			message = "\t" + message;
		}
		cd.find(".finish pre").append("<span class=\"info\">" + message + "</span>\n");
	};

	this.logSuccess = function(message){
		if (message == null) {
			message = "";
		}
		var msg = $("<span class=\"success\">");
		for (var i=0; i<o.level; i++) {
			msg.append("\t");
		}
		msg.append(message);
		cd.find(".finish pre").append(msg);
		cd.find(".finish pre").append("\n");
	};
	
	this.abort = function(){
		cd.find(".finish .well").show();
		cd.find(".setupButton").show();
		o.logError("Setup aborted");
	};
	
	this.stage1 = function(next){
		cd.find(".finish .well").hide();
		cd.find(".finish pre").show();
		cd.find(".setupButton").hide();

		o.logInfo("Setting up...");
		o.incLevel();
		o.logInfo("Setting up admin account...");

		var address = $(".setup .siteAddressInput").val();
		if (address.endsWith("/")) {
			address = address.substring(0, address.length - 1);
		}
		Global.api.call("AdminInterface", "setup", {
			siteAddress: address,
			serverName: $(".setup .serverNameInput").val(),
			serverDescription: $(".setup .serverDescriptionInput").val(),
			serverIcon: $(".setup .severIconInput").val(),
			adminName: $(".setup .adminNameInput").val(),
			adminUsername: $(".setup .adminUsernameInput").val(),
			adminPassword: $(".setup .adminPasswordInput").val()
		}, function(){
			o.incLevel();
			o.logSuccess("Admin account successfully setup");
			o.decLevel();
			o.stage = 1;
			next();
		}, function(message){
			o.logError(message);
			o.decLevel();
			o.abort();
		});
	};
	
	this.stage2 = function(){
		o.incLevel();
		o.logInfo("Setting up email...");
		Global.api.call("AuthInterface", "login", {username: $(".setup .adminUsernameInput").val(), password: $(".setup .adminPasswordInput").val()}, function(data){
			Global.api.call("SettingsInterface", "getServerSettings", {}, function(serverSettings){
				serverSettings.smtpServer = $(".setup .smtpServer").val();
				serverSettings.smtpProtocol = $(".setup .smtpProtocol").val();
				serverSettings.smtpPort = $(".setup .smtpPort").val();
				serverSettings.smtpUsername = $(".setup .smtpUsername").val();
				serverSettings.smtpPassword = $(".setup .smtpPassword").val();
				serverSettings.emailSenderAddress = $(".setup .emailSenderAddress").val();
				serverSettings.emailSenderName = $(".setup .emailSenderName").val();
				Global.api.call("SettingsInterface", "setServerSettings", {serverSettings: serverSettings}, function(data){
					o.logSuccess("Email successfully setup");
					o.decLevel();
					o.stage3();
				});			
			}, function(message){
				o.logError(message);
				o.decLevel();
				o.abort();
			});
		}, function(message){
			o.logError(message);
			o.decLevel();
			o.abort();
		});
	};
	
	this.nostage2 = function(){
		o.logInfo("Skipping email setup...");
		Global.api.call("AuthInterface", "login", {username: $(".setup .adminUsernameInput").val(), password: $(".setup .adminPasswordInput").val()}, function(data){
			o.stage3();
		}, function(message){
			o.logError(message);
			o.abort();
		});
	};
	
	this.installPluginBundle = function(requiredPlugins, callback) {
		var next = Object.keys(requiredPlugins)[0];
		o.logInfo("Installing " + next + "...");
		Global.api.call("PluginInterface", "getPluginBundle", requiredPlugins[next], function(pluginBundle){
			var latestVersion = pluginBundle.latestVersion;
			if (latestVersion == pluginBundle.installedVersion) {
				o.logError("Plugin version already installed" + "\n");
				delete requiredPlugins[next];
				if (Object.keys(requiredPlugins).length == 0) {
					callback();
					return;
				} else {
					o.installPluginBundle(requiredPlugins, callback);
				}
				return;
			}
			Global.api.call("PluginInterface", "getPluginInformation", {
				repository: latestVersion.repository,
				groupId: latestVersion.groupId,
				artifactId: latestVersion.artifactId,
				version: latestVersion.version
			}, function(plugins){
				plugins.forEach(function(plugin){
					plugin.enabled = true;
					plugin.installForAllUsers = true;
					plugin.installForNewUsers = true;
				});
				Global.api.call("PluginInterface", "installPluginBundle", {
					repository: latestVersion.repository,
					groupId: latestVersion.groupId,
					artifactId: latestVersion.artifactId,
					version: latestVersion.version,
					plugins: plugins
				}, function(){
					delete requiredPlugins[latestVersion.artifactId];
					o.pluginsInstalled[latestVersion.artifactId] = true;
					o.logSuccess("Successfully installed " + pluginBundle.name + " (" + latestVersion.groupId + ":" + latestVersion.artifactId + ":" + latestVersion.version + ")\n");
					if (Object.keys(requiredPlugins).length == 0) {
						callback();
						return;
					} else {
						o.installPluginBundle(requiredPlugins, callback);
					}
				}, function(message){
					o.logError(message + "\n");
					o.abort();
				});
			}, function(message){
				o.logError(message + "\n");
				o.abort();
			});
		}, function(message){
			o.logError(message + "\n");
			delete requiredPlugins[next];
			if (Object.keys(requiredPlugins).length == 0) {
				callback();
				return;
			} else {
				o.installPluginBundle(requiredPlugins, callback);
			}
		});
	}
	
	function installRequiredPlugins(requiredPlugins, callback) {
		var scratchmap = {};
		Object.keys(requiredPlugins).forEach(function(key, index) {
			scratchmap[key] = requiredPlugins[key];
		});
		Global.api.call("SettingsInterface", "setPluginStrictVersionChecking", {strict: true}, function(){
			Global.api.call("PluginInterface", "hasPreBuiltPlugins", {}, function(prebuilt){
				if (prebuilt) {
					var artifacts = [];
					for (var key in requiredPlugins) {
						artifacts.push(requiredPlugins[key].artifactId);
					}
					console.log("Prebuilt artifacts", artifacts);
					Global.api.call("PluginInterface", "installPreBuiltPlugins", {
						artifacts: artifacts
					}, function(){
						callback();
					});
				} else {
					Global.api.call("PluginInterface", "getInstalledPluginBundles", {}, function(bundles){
						bundles.forEach(function(bundle){
							var installedVersion = bundle.installedVersion;
							if (scratchmap[installedVersion.artifactId] != null) {
								o.logInfo("Already installed " + installedVersion.artifactId);
								delete scratchmap[installedVersion.artifactId];
							}
						});
						if (Object.keys(scratchmap).length > 0) {
							o.installPluginBundle(scratchmap, callback);
						} else {
							callback();
						}
					}, function(message){
						o.logError(message);
						o.abort();
					});
				}
			});
        }, function(message){
			o.logError(message);
			o.abort();
        });
	}
	
	this.installExtendedDataSchemas = function(callback){
		if (o.hasInternet) {
			o.logInfo("Installing all extended data schemas...");
			o.incLevel();
			Global.api.call("ServiceInterface", "getAllRepositoryExtendedDataSchemas", {usePre: true}, function(data){
				var requests = [];
				data.forEach(function(extendedDataSchema){
					var request = {
						interface: "ServiceInterface",
						method: "addExtendedDataSchema",
						parameters: {extendedDataSchema: extendedDataSchema}
					};
					requests.push(request);
				});
				Global.api.multiCall(requests, function(){
					data.forEach(function(extendedDataSchema){
						o.logSuccess(extendedDataSchema.name + " installed OK");
					});
					o.logSuccess("Extended Data Schemas installed OK");
					o.decLevel();
					callback();
				});
			});
		} else {
			o.logInfo("Not installing extended data schemas because there is no internet connection");
			callback();
		}
	};

	this.installPlugins = function(callback){
		if (o.hasInternet) {
			o.logInfo("Installing plugins...");
			
			var pluginsToInstall = {
			};
			cd.find(".plugins .maven input[type=\"checkbox\"]:checked").each(function(index, checkbox){
				var artifactId = $(checkbox).attr("class");
				pluginsToInstall[artifactId] = {
					repository: "https://repo1.maven.org/maven2",
					groupId: "org.opensourcebim",
					artifactId: artifactId
				};
			});
			
			o.incLevel();
			installRequiredPlugins(pluginsToInstall, function(){
				o.logSuccess("All remote plugins successfully installed");
				o.decLevel();
				callback();
			});
		} else {
			o.logInfo("Not installing plugins because there is no internet connection");
			callback();
		}
	};
	
	this.installUploadedPlugin = function(toInstall, callback){
		var reader  = new FileReader();
		var next = toInstall[0];
		
		reader.addEventListener("load", function () {
			var base64 = reader.result.substring(reader.result.indexOf(",") + 1);
			Global.api.call("PluginInterface", "installPluginBundleFromFile", {
				data: base64,
				installAllPluginsForAllUsers: true,
				installAllPluginsForNewUsers: true
			}, function(){
				o.logSuccess("Uploading plugin " + next.get(0).files[0].name + " installed OK");
				toInstall.splice(0, 1);
				if (toInstall.length == 0) {
					o.decLevel();
					callback();
				} else {
					o.installUploadedPlugin(toInstall, callback);
				}
			}, function(message){
				o.logError(message);
				callback();
			});
		}, false);

		var files = next.each(function(index, fileInput){
			var file = fileInput.files[0];
			if (file) {
				o.logInfo("Installing uploaded plugin " + file.name);
			    reader.readAsDataURL(file);
			} else {
				console.log("No file");
			}
		});
	};
	
	this.installUploadedPlugins = function(callback){
		var checkboxes = cd.find(".plugins .uploaded input[type=\"checkbox\"]:checked");
		if (checkboxes.size() == 0) {
			callback();
			return;
		}
		
		var toInstall = [];
		
		checkboxes.each(function(index, checkbox){
			var div = $(checkbox).parent().parent();
			var input = div.find(".fileInput");
			if (input.size() > 0) {
				if (input.get(0).files.length == 1) {
					toInstall.push(input);
				}
			}
		});
		
		o.incLevel();
		
		o.installUploadedPlugin(toInstall, callback);
	};
	
	this.stage3 = function(){
		o.logInfo("Checking internet connection _from_ your BIMserver...");
		o.incLevel();
		Global.api.call("ServiceInterface", "checkInternetConnection", {}, function(data){
			o.hasInternet = data;
			if (data == true) {
				o.logSuccess("Internet connection OK");
				o.decLevel();
			} else {
				o.logError("Your BIMserver does not seem to have a <a href=\"https://github.com/opensourceBIM/BIMserver/wiki/Outgoing-internet-connection\">working outgoing internet connection</a>.");
				o.decLevel();
			}
			if ($(".installExtendedDataSchemas").is(":checked")) {
				o.installExtendedDataSchemas(function(){
					o.installPlugins(function(){
						o.installUploadedPlugins(o.finished);
					});
				});
			} else {
				o.logInfo("Not installing extended data schemas");
				o.installPlugins(function(){
					o.installUploadedPlugins(o.finished);
				});
			}
		});
	};
	
	this.finished = function(){
		if (o.pluginsInstalled["bimviews"] != null) {
			var link = $("<a>Open BIMvie.ws</a>");
			link.click(function(){
				document.location = $(".setup .siteAddressInput").val() + "/apps/bimviews/";
			});
			o.logSuccess();
			o.logSuccess(link);
		} else {
			o.decLevel();
			o.logSuccess();
			o.logSuccess("Setup successful, <a href=\"/\">refresh to go to the status page</a>");
		}
	};
	
	this.finalStage = function(){
		Global.api.resolveUser(function(user){
			var address = $(".setup .siteAddressInput").val();
		});
	};
	
	this.setup = function(event){
		event.preventDefault(); // Required because the button is a "submit" button -> page refresh
		if (o.stage == 0) {
			o.stage1(cd.find(".setup .emailCheckBox").is(":checked") ? o.stage2 : o.nostage2);
		} else {
			o.stage2();
		}
	};
	
	function makeid() {
		  var text = "";
		  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

		  for (var i = 0; i < 15; i++)
		    text += possible.charAt(Math.floor(Math.random() * possible.length));

		  return text;
		}
	
	var id = makeid();
	cd.find(".identifierInput").val(id);
	var data = new Identicon(id, 140).toString();
	cd.find(".serverIcon").attr("src", "data:image/png;base64," + data);
	
	cd.find(".welcome input").enterpress(o.showAdmin);
	cd.find(".admin input").enterpress(o.showEmail);
	cd.find(".email input").enterpress(o.showPlugins);
	
	$("[rel=tooltip]").tooltip();
	$(".setup .setupButton").click(o.setup);
}
</script>